#pragma once

SYS_API vresult _AllocMemory(unsigned bytes,vstr* pString);
SYS_API vresult _ReallocMemory(unsigned newBytes,vstr s,vstr* pNew);
SYS_API vresult _FreeMemory(vstr s);

class StringAssistant
{
public:
	static vresult Alloc(unsigned bytes,vstr* pString){return _AllocMemory(bytes,pString);}
	static vresult Realloc(unsigned newBytes,vstr s,vstr* pNew){return _ReallocMemory(newBytes,s,pNew);}
	static vresult Free(vstr s){_FreeMemory(s);}

	static void LockString(vstr vs);
	static void UnLockString(vstr vs);
	static int32 GetStringRefCount(vstr vs);
	static int32 GetStringCapacity(vstr vs);
	static int32 GetStringLength(vstr vs);
	static void SetStringLength(vstr vs,int32 lengthBytes);
};

//////////////////////////////////////////////////////////////////////////
//inline
inline void StringAssistant::LockString(vstr vs)
{
	if(vs)
	{
		++( *(reinterpret_cast<int32*>(vs-12)) );
	}
}

inline void StringAssistant::UnLockString(vstr vs)
{
	if(vs)
	{
		int32& ref=*(reinterpret_cast<int32*>(vs-12));
		--ref;
		if(ref==0)
			_FreeMemory(vs);
	}
}

inline int32 StringAssistant::GetStringRefCount(vstr vs)
{
	ASSERT(vs);
	return *(reinterpret_cast<int32*>(vs-12));
}

inline int32 StringAssistant::GetStringCapacity(vstr vs)
{
	if(vs)
		return *(reinterpret_cast<int32*>(vs-8));
	return 0;
}

inline int32 StringAssistant::GetStringLength(vstr vs)
{
	if(vs)
		return *(reinterpret_cast<int32*>(vs-4));
	return 0;
}

inline void StringAssistant::SetStringLength(vstr vs,int32 lengthBytes)
{
	ASSERT(vs);
	*(reinterpret_cast<int32*>(vs-4))=lengthBytes;
}